package com.moyv.schoolbbs.base.chat.server;

import com.moyv.schoolbbs.base.chat.data.SealData;
import com.moyv.schoolbbs.bean.model.User;
import com.moyv.schoolbbs.util.ToastUtils;

import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.iqregister.AccountManager;
import org.jivesoftware.smackx.search.ReportedData;
import org.jivesoftware.smackx.search.UserSearchManager;
import org.jivesoftware.smackx.xdata.Form;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;

import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.moyv.schoolbbs.config.URLConstant.C_DOMAIN;
import static com.moyv.schoolbbs.config.URLConstant.C_HOST;
import static com.moyv.schoolbbs.config.URLConstant.C_PORT;
import static com.moyv.schoolbbs.config.URLConstant.C_SOURCE;

public class ConnectionServer {

    private AbstractXMPPConnection connection;

    public AbstractXMPPConnection getConnection() {
        return connection;
    }

    public ConnectionServer() {
        init();
    }

    public AbstractXMPPConnection init() {

//        new Thread(() -> {
//
//        });

        try {
            System.out.println("正在连接Chat服务。。。");
            XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
                    .setResource(Resourcepart.from(C_SOURCE))//固定源
                    .setHostAddress(InetAddress.getByName(C_HOST))
                    .setPort(C_PORT)
                    .setXmppDomain(C_DOMAIN)
                    .setSendPresence(false)//以离线方式登录,以便获取离线消息
                    .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                    .build();
            connection = new XMPPTCPConnection(configuration);
            connection.connect();
            System.out.println("Chat服务连接成功");
        } catch (Exception e) {
            System.out.println("Chat服务连接失败" + e.getLocalizedMessage());
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 注册
     *
     * @param account  注册帐号
     * @param password 注册密码
     * @param name     用户名
     * @return true 注册成功 false 注册失败
     */
    public boolean register(String account, String name, String password) {
        try {
            if (!connection.isConnected()) {
                connection.connect();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            HashMap<String, String> map = new HashMap<>();
            map.put("name", name);
            AccountManager instance = AccountManager.getInstance(connection);
            instance.sensitiveOperationOverInsecureConnection(true);
            instance.createAccount(Localpart.from(account), password, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /*
     * 登录
     *
     * */
    public boolean login(String user, String pass) {
        if (connection == null && connection.isConnected())
            return false;
        try {
            connection.login(user, pass);
            System.out.println("Chat服务登录成功！");
            return true;
        } catch (Exception e) {
            System.out.println("Chat服务登录失败！");
            e.printStackTrace();
            return false;
        }
    }

    /*
     * 登出
     *
     * */
    public boolean logout() {
        if (connection != null && isConnected() && isLogin()) {
            try {
                connection.sendStanza(new Presence(Presence.Type.unavailable));
                connection.disconnect();
                init();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return false;
    }

    /*
     * 是否连接服务器
     *
     * */
    public boolean isConnected() {
        return connection.isConnected();
    }

    /*
     * 是否登录
     *
     * */
    public boolean isLogin() {
        return connection.isAuthenticated();
    }

    /*
     * 注销当前用户
     *
     * */
    public void deleteUser() {
        if (connection != null) {
            try {
                AccountManager.getInstance(connection).deleteAccount();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 获取用户在线状态
     *
     * */
    public boolean getOnline(String id) {
        return false;
    }

    //搜索
    public List<User> search(String account) {
        List<User> users = new ArrayList<>();
        try {
            UserSearchManager usm = new UserSearchManager(connection);
            //本例用的smack:4.3.4版本，getSearchForm方法传的是DomainBareJid类型，而之前的版本是String类型，大家在使用的时候需要特别注意
            //而转换DomainBareJid的方式如下面的例子所示：JidCreate.domainBareFrom("search." + getConnection().getXMPPServiceDomain())
            Form searchForm = usm.getSearchForm(JidCreate.domainBareFrom("search." + connection.getXMPPServiceDomain()));
            if (searchForm == null) {
                return users;
            }
            //这里设置了Username为true代码是根据用户名查询用户，search代表查询字段
            //smack:4.3.4版本是下面的字段，但之前的版本会有些不一样，所以在用的时候最好看下xmpp交互的log，里面有相应的字段值
            Form answerForm = searchForm.createAnswerForm();
            answerForm.setAnswer("Username", true);
            answerForm.setAnswer("Name", true);
            answerForm.setAnswer("search", account);
            ReportedData data = usm.getSearchResults(answerForm, JidCreate.domainBareFrom("search." + connection.getXMPPServiceDomain()));
            List<ReportedData.Row> rowList = data.getRows();

            //此处返回的字段名如下所示，之前的版本可能有所变化，使用的时候需要注意
            for (ReportedData.Row row : rowList) {
                String jid = row.getValues("jid").toString().replace("[", "");
                String username = row.getValues("Username").toString().replace("[", "");
                String name = row.getValues("Name").toString().replace("[", "");
//                String email = row.getValues("Email").toString();
                // 若存在，则有返回,UserName一定非空，其他两个若是有设，一定非空
                jid = jid.replace("]", "");
                name = name.replace("]", "");
                username = username.replace("]", "");
                System.out.println("搜索账号信息：" + jid + "," + username + "," + name);
                users.add(new User(username, name, SealData.getPhoto(username), false));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return users;
    }

    public User searchFirst(String account) {
        List<User> users = search(account);
        if (users.size() > 0)
            return users.get(0);
        return null;
    }
}
